<?php
/**
 *  💡 免责声明：本软件不得用于商业用途，仅做学习交流
 *  ⚠️ 权利声明：本软件由版权人提供产品技术支持
 *  📅 项目编号：NX2025-0135
 */
namespace App\Jobs;

use App\Models\PerformanceLevel;
use App\Models\PerformanceMember;
use App\Models\User;
use App\Models\UserTotalRevenue;
use App\Service\Notifications\NotificationService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;

class UserAgentLevelJob implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public $tries = 5;

    public $maxExceptions = 3;

    public $backoff = [30, 60, 300, 600, 1800];

    public $timeout = 300;

    /**
     * 解除任务唯一锁的秒数.
     *
     * @var int
     */
    public $uniqueFor = 8000;

    private $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function handle()
    {
        DB::transaction(function () {
            $teamData = $this->fetchTeamPerformance();
            $smallSum = $this->calculateSmallSum($teamData);
            $level = $this->matchPerformanceLevel($smallSum);

            $this->updateUserLevel($level);
            $this->savePerformanceMember($teamData, $smallSum);
        });
    }

    private function fetchTeamPerformance(): array
    {
        $revenues = UserTotalRevenue::query()
            ->whereIn('user_id', $this->user->queryChildren()->select('id'))
            ->select('user_id', 'value', 'self')
            ->get();

        $teamRevenue = $revenues->mapWithKeys(function ($item) {
            return [
                $item->user_id => bcadd($item->value, $item->self, 2),
            ];
        });

        return [
            'total' => $teamRevenue->sum(),
            'max_team' => $teamRevenue->max() ?: '0.00',
            'teams' => $teamRevenue->toArray(),
        ];
    }

    private function calculateSmallSum(array $teamData): string
    {
        $smallSum = bcsub($teamData['total'], $teamData['max_team'], 2);
        return bccomp($smallSum, '0', 2) < 0 ? '0.00' : $smallSum;
    }

    private function matchPerformanceLevel(string $amount): ?PerformanceLevel
    {
        return PerformanceLevel::query()
            ->where('min_amount', '<=', $amount)
            ->where('max_amount', '>', $amount)
            ->orderByDesc('min_amount')
            ->first();
    }

    private function updateUserLevel(?PerformanceLevel $level): void
    {
        if (! $level || $level->id <= $this->user->agent_level) {
            return;
        }

        $this->user->agent_level = $level->id;
        $this->user->save();

        NotificationService::make()->SystemNotify(
            $this->user,
            sprintf('恭喜您业绩等级提升:%s', $level->name)
        );
    }

    private function savePerformanceMember(array $teamData, string $smallSum): void
    {
        PerformanceMember::query()->updateOrCreate(
            ['user_id' => $this->user->id],
            [
                'total_amount' => $teamData['total'] ?? '0.00',
                'max_team_amount' => $teamData['max_team'] ?? '0.00',
                'small_teams_sum' => $smallSum,
                'calculation_date' => now()->toDateTimeString(),
                'team_data' => $teamData['teams'] ?? [],
            ]
        );
    }
}
